package com.wangyb.wework.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.wangyb.wework.enums.ContactAuthEnum;
import com.wangyb.wework.enums.EmployeeStatusEnum;
import com.wangyb.wework.enums.GenderEnum;
import com.wangyb.wework.enums.RespEmployeeErrCodeEnum;
import com.wangyb.wework.enums.updatetime.TypeEnum;
import com.wangyb.wework.entity.*;
import com.wangyb.wework.entity.employee.*;
import com.wangyb.wework.exception.CommonException;
import com.wangyb.wework.mapper.employee.WwEmployeeMapper;
import com.wangyb.wework.service.IWwEmployeeDeptService;
import com.wangyb.wework.service.IWwEmployeeService;
import com.wangyb.wework.service.IWwEmployeeStatisticService;
import com.wangyb.wework.service.IWwUpdateTimeService;
import com.wangyb.wework.utils.DownUploadQueueUtils;
import com.wangyb.wework.utils.FileUtils;
import com.wangyb.wework.utils.WxApiUtils;
import com.wangyb.wework.utils.ali.AliyunOssUtils;
import com.wangyb.wework.wxApi.UserBehaviorDataResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Author: wangyb
 * @Date: 2021/6/28 1:55 下午
 */
@Service
public class WwEmployeeServiceImpl extends ServiceImpl<WwEmployeeMapper, WwEmployee> implements IWwEmployeeService {



	@Autowired
	private IWwUpdateTimeService wwUpdateTimeService;
	@Autowired
	private ISysDeptService sysDeptService;
	@Autowired
	private ISysUserService userService;
	@Autowired
	private IWwEmployeeDeptService employeeDeptService;
	@Autowired
	private IWwEmployeeStatisticService employeeStatisticService;

	/**
	 * 同步部门和成员
	 *
	 * @param corpId
	 */
	@Override
	public void syncWxEmployee(Long corpId) {
		syncDepartment(corpId);
		syncEmployee(corpId);
		wwUpdateTimeService.updateSynTime(corpId, TypeEnum.EMPLOYEE);
	}
	@Override
	@Transactional(rollbackFor = {RuntimeException.class, Exception.class})
	public void syncDepartment(Long corpId) {
		String result = WxApiUtils.requestDepartmentListApi(corpId);
		log.debug(" >>>>>>> 微信部门列表: " + result);
		if (null == result) {
			log.error(">>>>>>> 微信部门列表获取失败: null");
			return;
		}

		List<WXDepartmentDTO> wxEmployeeDTOList = JSONArray.parseArray(result, WXDepartmentDTO.class);
		if (null == wxEmployeeDTOList || wxEmployeeDTOList.isEmpty()) {
			return;
		}

		Map<Long, WXDepartmentDTO> map = new HashMap<>(0);
		for (WXDepartmentDTO e : wxEmployeeDTOList) {
			map.put(e.getId(), e);
		}

		List<SysDept> workDeptEntityList = sysDeptService.lambdaQuery()
			.eq(SysDept::getCorpId, corpId)
			.list();

		for (SysDept wde : workDeptEntityList) {
			map.remove(wde.getWxDeptId());
		}
		workDeptEntityList.clear();

		map.forEach((integer, wxDepartmentDTO) -> {
			SysDept entity = new SysDept();
			entity.setWxDeptId(wxDepartmentDTO.getId());
			entity.setCorpId(corpId);
			//TODO 租户id要处理，分定时任务同步和手工操作同步
//			entity.setTenantId();
			entity.setDeptName(wxDepartmentDTO.getName());
			entity.setParentId(getMainDepartmentId(corpId, wxDepartmentDTO.getParentid()));
			entity.setWxParentId(wxDepartmentDTO.getParentid());
			entity.setOrderNum(String.valueOf(wxDepartmentDTO.getOrder()));

			workDeptEntityList.add(entity);
		});
		map.clear();

		for (SysDept dept : workDeptEntityList) {
			sysDeptService.insertDept(dept);
		}
		List<SysDept> updateList = sysDeptService.lambdaQuery().eq(SysDept::getCorpId, corpId).list();
		for (SysDept dept : workDeptEntityList) {
			SysDept sysDept = sysDeptService.lambdaQuery()
				.eq(SysDept::getDeptId, corpId)
				.eq(SysDept::getWxDeptId, dept.getWxDeptId())
				.one();
			if (sysDept != null){
				dept.setParentId(sysDept.getDeptId());
				sysDeptService.updateDept(dept);
			}
		}
	}
	@Override
	public void syncEmployee(Long corpId) {
		// 获取部门信息
		List<SysDept> deptEntityList = sysDeptService.lambdaQuery()
			.select(SysDept::getWxDeptId)
			.eq(SysDept::getCorpId, corpId)
			.list();

		// 遍历部门信息, 拉取微信成员信息
		for (SysDept dept : deptEntityList) {
			syncEmpByWxDepartId(corpId, dept.getWxDeptId());
		}
	}
	@Transactional(rollbackFor = {RuntimeException.class, Exception.class})
	public void syncEmpByWxDepartId(Long corpId, Long wxDeptId) {
		String result = WxApiUtils.requestUserListApi(corpId, wxDeptId);
		log.debug(" >>>>>> 微信部门下成员详情列表: " + result);
		if (null == result) {
			log.error(" >>>>>> 微信部门下成员详情列表获取失败: null");
			return;
		}

		List<WXEmployeeDTO> wxEmployeeDTOList = JSONArray.parseArray(result, WXEmployeeDTO.class);
		if (null == wxEmployeeDTOList || wxEmployeeDTOList.isEmpty()) {
			return;
		}

		Map<String, WXEmployeeDTO> map = new HashMap<>(0);
		for (WXEmployeeDTO e : wxEmployeeDTOList) {
			map.put(e.getUserid(), e);
		}

		List<WwEmployee> employeeEntityList = lambdaQuery()
			.select(WwEmployee::getWxUserId)
			.eq(WwEmployee::getCorpId, corpId)
			.list();

		for (WwEmployee e : employeeEntityList) {
			map.remove(e.getWxUserId());
		}

		List<WwEmployee> newEmployeeEntityList = new ArrayList<>();
		map.forEach((key, wxe) -> {
			WwEmployee employee = transWxEmpDtoToEmpEntity(corpId, wxe);
			newEmployeeEntityList.add(employee);
		});

		if (!newEmployeeEntityList.isEmpty()) {
			saveBatch(newEmployeeEntityList);
			// 更新成员与部门表索引
			for (WXEmployeeDTO dto : map.values()) {
				updateEmpDeptIndex(corpId, dto);
			}
		}
	}
	@Override
	@Transactional(rollbackFor = {RuntimeException.class, Exception.class})
	public void syncEmployeeStatistic(Long corpId) {
		// 获取成员信息
		List<WwEmployee> employeeEntityList = lambdaQuery()
			.select(WwEmployee::getId, WwEmployee::getWxUserId, WwEmployee::getLastBehaviorStatTime)
			.eq(WwEmployee::getCorpId, corpId)
			.list();

		for (WwEmployee emp : employeeEntityList) {
			Long startTime = getLastBehaviorSyncTime(emp.getLastBehaviorStatTime());
			Long endTime = DateUtil.beginOfDay(new Date()).getTime() / 1000;
			if (startTime>endTime){
				continue;
			}

			log.debug("startTime:"+startTime+"; endTime:"+endTime);
			UserBehaviorDataResp resp = WxApiUtils.getUserBehaviorData(corpId, emp.getWxUserId(),startTime,endTime);
			log.debug(" >>>>>>>>> 微信员工客户统计数据: " + resp);

			List<WXEmpStatisticDTO> statisticDTOList = resp.getBehaviorData().toJavaList(WXEmpStatisticDTO.class);;
			if (null == statisticDTOList || statisticDTOList.isEmpty()) {
				log.error("获取微信员工统计数据");
				return;
			}
			for (WXEmpStatisticDTO dto:statisticDTOList){
				WwEmployeeStatistic entity = new WwEmployeeStatistic();
				entity.setCorpId(corpId);
				entity.setEmployeeId(emp.getId());
				entity.setNewApplyCnt(dto.getNewApplyCnt());
				entity.setNewContactCnt(dto.getNewContactCnt());
				entity.setChatCnt(dto.getChatCnt());
				entity.setMessageCnt(dto.getMessageCnt());
				entity.setReplyPercentage(dto.getReplyPercentage() ==null?0:(int) (dto.getReplyPercentage() * 100));
				entity.setAvgReplyTime(dto.getAvgReplyTime());
				entity.setNegativeFeedbackCnt(dto.getNegativeFeedbackCnt());
				entity.setStatTime(dto.getStatTime());
				employeeStatisticService.saveOrUpdate(entity);
				new LambdaUpdateChainWrapper<>(getBaseMapper())
					.eq(WwEmployee::getId,emp.getId())
					.or(e->e.isNull(WwEmployee::getLastBehaviorStatTime)
						.lt(WwEmployee::getLastBehaviorStatTime,entity.getStatTime()))
					.set(WwEmployee::getLastBehaviorStatTime,entity.getStatTime())
					.update();
			}
		}
	}
	private Long getLastBehaviorSyncTime(Integer lastBehaviorStatTime) {
		//最多查询30天之内的数据
		int before30DaysInSecond = (int)DateUtil.currentSeconds() - 15 * 24 * 60 * 60;
		if (lastBehaviorStatTime == null || lastBehaviorStatTime < before30DaysInSecond ){
			return Long.valueOf(before30DaysInSecond);
		}
		return Long.valueOf(lastBehaviorStatTime)+ 24 * 60 * 60;
	}


	@Override
	@Transactional(rollbackFor = {RuntimeException.class, Exception.class})
	public void updateEmpDeptIndex(Long corpId, WXEmployeeDTO dto) {
		// 根据员工微信 id, 获取员工 id
		Long empId = getEmpIdByWxUserId(corpId, dto.getUserid());

		List<WwEmployeeDept> workEmployeeDepartmentEntityList = employeeDeptService.list(
			new QueryWrapper<WwEmployeeDept>()
				.eq("employee_id", empId)
		);

		// 循环员工微信部门 id, 获取对应部门 id
		List<Long> depts = dto.getDepartment();
		List<Integer> orders = dto.getOrder();
		List<Integer> isLeaderInDepts = dto.getIsLeaderInDept();

		WwEmployeeDept entity;

		List<Integer> hasList = new ArrayList<>();
		List<WwEmployeeDept> updateList = new ArrayList<>();

		if (!workEmployeeDepartmentEntityList.isEmpty()) {
			for (int i = 0; i < depts.size(); i++) {
				Long deptId = depts.get(i);
				int order = orders.get(i);
				int isLeaderInDept = isLeaderInDepts.get(i);

				// 查询对应部门 id
				Long dId = getMainDepartmentId(corpId, deptId);

				for (int j = 0; j < workEmployeeDepartmentEntityList.size(); j++) {
					entity = workEmployeeDepartmentEntityList.get(j);
					if (dId == entity.getDeptId()) {
						hasList.add(i);
						entity.setIsLeaderInDept(isLeaderInDept);
						entity.setOrder(order);
						updateList.add(entity);
						workEmployeeDepartmentEntityList.remove(entity);
						break;
					}
				}
			}
		}

		for (int hasIndex : hasList) {
			depts.remove(hasIndex);
			orders.remove(hasIndex);
			isLeaderInDepts.remove(hasIndex);
		}

		List<WwEmployeeDept> newList = new ArrayList<>();

		for (int i = 0; i < depts.size(); i++) {
			Long deptId = depts.get(i);
			int order = orders.get(i);
			int isLeaderInDept = isLeaderInDepts.get(i);

			// 查询对应部门 id
			Long dId = getMainDepartmentId(corpId, deptId);

			entity = new WwEmployeeDept();
			entity.setEmployeeId(empId);
			entity.setDeptId(dId);
			entity.setIsLeaderInDept(isLeaderInDept);
			entity.setOrder(order);

			newList.add(entity);
		}

		List<Long> removeIds = new ArrayList<>();
		for (WwEmployeeDept employeeDepartmentEntity : workEmployeeDepartmentEntityList) {
			removeIds.add(employeeDepartmentEntity.getId());
		}

		if (!removeIds.isEmpty()) {
			employeeDeptService.getBaseMapper().deleteBatchIds(removeIds);
		}
		if (!updateList.isEmpty()) {
			employeeDeptService.updateBatchById(updateList);
		}
		if (!newList.isEmpty()) {
			employeeDeptService.saveBatch(newList);
		}
	}
	private Long getMainDepartmentId(Long corpId, Long wxDeptId) {
		if (wxDeptId == 0L) {
			return 0L;
		}
		try {
			SysDept sysDept = new SysDept();
			sysDept.setCorpId(corpId);
			sysDept.setWxDeptId(wxDeptId);
			return sysDeptService.lambdaQuery()
				.eq(SysDept::getCorpId, corpId)
				.eq(SysDept::getWxDeptId, wxDeptId)
				.one()
				.getDeptId();
		} catch (Exception e) {
			// 部门 ID 不存在
			log.error(">>>>>>>>> 获取部门 id 出错, 部门 wxDeptId: " + wxDeptId + "不存在");
		}
		return 0L;
	}
	private Long getEmpIdByWxUserId(Long corpId, String wxUserId) {
		// 根据员工微信 id, 获取员工 id
		WwEmployee employeeEntity = lambdaQuery()
			.eq(WwEmployee::getCorpId, corpId)
			.eq(WwEmployee::getWxUserId, wxUserId)
			.one();
		if (employeeEntity == null) {
			throw new CommonException(RespEmployeeErrCodeEnum.EMPLOYEE_NO_EXISTS);
		} else {
			return employeeEntity.getId();
		}
	}
	private WwEmployee transWxEmpDtoToEmpEntity(Long corpId, WXEmployeeDTO dto) {
		WwEmployee employee = new WwEmployee();
		employee.setWxUserId(dto.getUserid());
		employee.setCorpId(corpId);
		employee.setName(dto.getName());
		employee.setMobile(dto.getMobile());
		employee.setPosition(dto.getPosition());
		employee.setGender(dto.getGender());
		employee.setEmail(dto.getEmail());
		employee.setAvatar(dto.getAvatar());
		employee.setThumbAvatar(dto.getThumbAvatar());
		employee.setTelephone(dto.getTelephone());
		employee.setAlias(dto.getAlias());
		employee.setExtattr(dto.getExtattr());
		employee.setStatus(dto.getStatus());
		employee.setExternalProfile(dto.getExternalProfile());
		employee.setExternalPosition(dto.getExternalPosition());
		employee.setAddress(dto.getAddress());
		employee.setOpenUserId(dto.getOpenUserid());
		employee.setWxMainDeptId(dto.getMainDepartment());
		employee.setMainDeptId(getMainDepartmentId(corpId, dto.getMainDepartment()));

		// 是否配置外部联系人权限（1.是 2.否）
		employee.setContactAuth(hasContactAuth(corpId, dto.getUserid()) ? 1 : 2);

		// 关联子账户
		List<SysUser> userEntityList = userService.lambdaQuery()
			.select(SysUser::getUserId)
			.eq(SysUser::getPhonenumber, dto.getMobile())
			.list();
		if (!userEntityList.isEmpty()) {
			employee.setLogUserId(userEntityList.get(0).getUserId());
		}

		String avatarUrl = dto.getAvatar();
		String thumbAvatarUrl = dto.getThumbAvatar();
		String qrCodeUrl = dto.getQrCode();

		String avatarKey = FileUtils.getFileNameOfEmpAvatar();
		String thumbAvatarKey = FileUtils.getFileNameOfEmpThumbAvatar();
		String qrCodeKey = FileUtils.getFileNameOfEmpQrCode();

		employee.setAvatar(avatarKey);
		employee.setThumbAvatar(thumbAvatarKey);
		employee.setQrCode(qrCodeKey);

		DownUploadQueueUtils.uploadFileByUrl(avatarKey, avatarUrl);
		DownUploadQueueUtils.uploadFileByUrl(thumbAvatarKey, thumbAvatarUrl);
		DownUploadQueueUtils.uploadFileByUrl(qrCodeKey, qrCodeUrl);

		return employee;
	}

	/**
	 * 是否有外部联系人权限
	 * @param corpId
	 * @param wxUserId
	 * @return
	 */
	private boolean hasContactAuth(Long corpId, String wxUserId) {
		return getFollowUserList(corpId).contains(wxUserId);
	}
	private static Map<Long, List<String>> followUserMap = new HashMap<>();

	private List<String> getFollowUserList(Long corpId) {
		List<String> list = followUserMap.get(corpId);
		if (list == null) {
			String followUserStr = WxApiUtils.requestFollowUserListApi(corpId);
			List<String> tempList = JSONArray.parseArray(followUserStr, String.class);
			if (tempList != null && !tempList.isEmpty()) {
				list = tempList;
				followUserMap.put(corpId, list);
			}
		}
		return list;
	}

	@Override
	public TableDataInfo<EmployeeBO> index(EmployeeQueryBO req){
		//TODO corpId需要从当前登录用户中取
		Long corpId = 1L;

		Integer status = req.getStatus();
		String name = req.getName();
		String contactAuth = req.getContactAuth();

		LambdaQueryWrapper<WwEmployee> wrapper = new LambdaQueryWrapper<WwEmployee>();
		//TODO 这里需要过滤数据权限 dataScope
		wrapper.select(
			WwEmployee::getId,
			WwEmployee::getName,
			WwEmployee::getThumbAvatar,
			WwEmployee::getStatus,
			WwEmployee::getContactAuth,
			WwEmployee::getGender
		);
		wrapper.eq(WwEmployee::getCorpId, corpId);
		if (null != status && status > 0 && status <= 5) {
			wrapper.eq(WwEmployee::getStatus, status);
		}
		if (null != name && !name.isEmpty()) {
			wrapper.like(WwEmployee::getName, name);
		}
		if (null != contactAuth) {
			wrapper.eq(WwEmployee::getContactAuth, contactAuth);
		}
		TableDataInfo<WwEmployee> data = PageUtils.buildDataInfo(page(PageUtils.buildPage(),wrapper));
		List<WwEmployee> rows = data.getRows();
		List<Long> eIds = new ArrayList<>();
		for (WwEmployee e : rows) {
			eIds.add(e.getId());
		}

		Map<Long, WwEmployeeStatistic> map = new HashMap<>();
		if (!eIds.isEmpty()) {
			List<WwEmployeeStatistic> employeeStatistics = employeeStatisticService.list(
				new QueryWrapper<WwEmployeeStatistic>()
					.select("new_apply_cnt", "new_contact_cnt", "chat_cnt", "message_cnt", "reply_percentage",
						"avg_reply_time", "negative_feedback_cnt")
					.eq("corp_id", corpId)
					.in("employee_id", eIds)
			);
			for (WwEmployeeStatistic employeeStatistic : employeeStatistics) {
				map.put(employeeStatistic.getEmployeeId(), employeeStatistic);
			}
		}
		List<EmployeeBO> employeeBOList = new ArrayList<>();
		EmployeeBO employeeBO;
		for (WwEmployee employeeEntity : rows) {
			employeeBO = new EmployeeBO();
			employeeBO.setId(employeeEntity.getId());
			employeeBO.setName(employeeEntity.getName());
			String thumbAvatar = AliyunOssUtils.getUrl(employeeEntity.getThumbAvatar());
			employeeBO.setThumbAvatar(thumbAvatar);
			employeeBO.setStatus(employeeEntity.getStatus());
			employeeBO.setContactAuth(employeeEntity.getContactAuth());
			employeeBO.setGender(GenderEnum.getMsgByCode(employeeEntity.getGender()));
			employeeBO.setContactAuthName(ContactAuthEnum.getMsgByCode(employeeEntity.getContactAuth()));
			employeeBO.setApplyNums(employeeEntity.getId());
			employeeBO.setStatusName(EmployeeStatusEnum.getMsgByCode(employeeEntity.getStatus()));

			WwEmployeeStatistic employeeStatistic = map.get(employeeEntity.getId());
			if (employeeStatistic != null) {
				employeeBO.setAddNums(employeeStatistic.getNewContactCnt());
				employeeBO.setMessageNums(employeeStatistic.getMessageCnt());
				employeeBO.setSendMessageNums(employeeStatistic.getMessageCnt());
				employeeBO.setReplyMessageRatio(employeeStatistic.getReplyPercentage());
				employeeBO.setAverageReply(employeeStatistic.getAvgReplyTime());
				employeeBO.setInvalidContact(employeeStatistic.getNegativeFeedbackCnt());
			}

			employeeBOList.add(employeeBO);
		}
		TableDataInfo<EmployeeBO> resp = new TableDataInfo<>(employeeBOList,data.getTotal());
		return resp;
	}
	@Override
	public WwEmployee getByWxUserid(String wxUserid){
		return this.lambdaQuery().eq(WwEmployee::getWxUserId,wxUserid).one();
	}
	@Override
	public WwEmployee getByUserId(Long userId){
		return this.lambdaQuery().eq(WwEmployee::getLogUserId,userId).one();
	}
}
